package platformer.view.sprites;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.net.URL;

import javax.imageio.ImageIO;

import platformer.view.sprites.states.*;


public class AnimatedSprite {
	
	final private int 		width 	= 96;
	final private int 		height 	= 96;
	
	private AnimationState	animationSate = new Idle();

	private String 			spriteSheetName;
	private BufferedImage 	sprite;
	
	private int frame = 1;
	
	public String getSpriteSheet()
	{
		return spriteSheetName;
	}

	public void setSpriteSheet(String spriteSheet)
	{
		try
		{
			URL imageURL = getClass().getClassLoader().getResource( spriteSheet );
			String path = imageURL.getPath().toString();
			System.out.print( "Intentando leer: "+path+"\n" );
			sprite = ImageIO.read( imageURL );		
			
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void init(String spriteSheet) {
		this.setSpriteSheet( spriteSheet );
	}
	
	public AnimatedSprite(String spriteSheet) {
		init(spriteSheet);
	}
	
	public void setAnimationSate(AnimationState animationSate)
	{
		if(this.animationSate.equals( animationSate ))return;
		this.animationSate = animationSate;
	}


	public void setToIdle()
	{
		this.animationSate = this.animationSate.getIdle();		
	}
	
	public BufferedImage getNextFrame() {		
		
		if(frame < animationSate.getFrames()) frame++;
		else frame = 1;
		
		BufferedImage returnImage = sprite.getSubimage(
				( animationSate.getX() + frame - 1) * width,
				animationSate.getY() * height,
	            width,
	            height
	        );
		
		if(animationSate.flipHorizontal())
			returnImage = horizontalflip(returnImage);
		
		if(animationSate.flipVertical())
			returnImage = verticalflip(returnImage);
		
		return setbackgroundToTransparent(returnImage);
	}
	
	/**
     * This method flips the image horizontally
     * @param img --> BufferedImage Object to be flipped horizontally
     * @return
     */
	private BufferedImage horizontalflip(BufferedImage img) {
        int w = img.getWidth();
        int h = img.getHeight();
        BufferedImage dimg = new BufferedImage(w, h, img.getType());
        Graphics2D g = dimg.createGraphics();
        /*
         * img - the specified image to be drawn. This method does nothing if
         * img is null. dx1 - the x coordinate of the first corner of the
         * destination rectangle. dy1 - the y coordinate of the first corner of
         * the destination rectangle. dx2 - the x coordinate of the second
         * corner of the destination rectangle. dy2 - the y coordinate of the
         * second corner of the destination rectangle. sx1 - the x coordinate of
         * the first corner of the source rectangle. sy1 - the y coordinate of
         * the first corner of the source rectangle. sx2 - the x coordinate of
         * the second corner of the source rectangle. sy2 - the y coordinate of
         * the second corner of the source rectangle. observer - object to be
         * notified as more of the image is scaled and converted.
         *
         */
        g.drawImage(img, 0, 0, w, h, w, 0, 0, h, null);
        g.dispose();
        return dimg;
    }
 
    /**
     * This method flips the image vertically
     * @param img --> BufferedImage object to be flipped
     * @return
     */
    private BufferedImage verticalflip(BufferedImage img) {
        int w = img.getWidth();
        int h = img.getHeight();
        BufferedImage dimg = new BufferedImage(w, h, img.getColorModel()
                .getTransparency());
        Graphics2D g = dimg.createGraphics();
        g.drawImage(img, 0, 0, w, h, 0, h, w, 0, null);
        g.dispose();
        return dimg;
    }
    
    @SuppressWarnings("unused")
	private Image TransformGrayToTransparency(BufferedImage image)
	{
		ImageFilter filter = new RGBImageFilter()
		{
			public final int filterRGB(int x, int y, int rgb)
			{
				return (rgb << 8) & 0xFF000000;
			}
		};

		ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
		return Toolkit.getDefaultToolkit().createImage(ip);
	}

    private Image TransformColorRangeToTransparency(BufferedImage image, Color c1, Color c2)
	{
		// Primitive test, just an example
		final int r1 = c1.getRed();
		final int g1 = c1.getGreen();
		final int b1 = c1.getBlue();
		final int r2 = c2.getRed();
		final int g2 = c2.getGreen();
		final int b2 = c2.getBlue();
		ImageFilter filter = new RGBImageFilter()
		{
			public final int filterRGB(int x, int y, int rgb)
			{
				int r = (rgb & 0xFF0000) >> 16;
				int g = (rgb & 0xFF00) >> 8;
				int b = rgb & 0xFF;
				if (r >= r1 && r <= r2 &&
						g >= g1 && g <= g2 &&
						b >= b1 && b <= b2)
				{
					// Set fully transparent but keep color
					return rgb & 0xFFFFFF;
				}
				return rgb;
			}
		};

		ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
		return Toolkit.getDefaultToolkit().createImage(ip);
	}

	private BufferedImage ImageToBufferedImage(Image image, int width, int height)
	{
		BufferedImage dest = new BufferedImage(
				width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = dest.createGraphics();
		g2.drawImage(image, 0, 0, null);
		g2.dispose();
		return dest;
	}
    
    private BufferedImage setbackgroundToTransparent( BufferedImage image ) {    	
    	Image temp = TransformColorRangeToTransparency( image, new Color(64,64,64), new Color(64,64,64) );    	
    	return ImageToBufferedImage( temp, temp.getWidth( null ), temp.getHeight( null ) );
    }
	
}